package http

import (
	"gitee.com/captials-team/ubdframe/src/common/consts"
	"gitee.com/captials-team/ubdframe/src/common/utils"
	"gitee.com/captials-team/ubdframe/src/domain/configstc"
	"gitee.com/captials-team/ubdframe/src/domain/dto"
	"gitee.com/captials-team/ubdframe/src/domain/dto/paginate"
	"gitee.com/captials-team/ubdframe/src/domain/dto/reqdata"
	"gitee.com/captials-team/ubdframe/src/domain/dto/respdata"
	"gitee.com/captials-team/ubdframe/src/domain/interfaces"
	"gitee.com/captials-team/ubdframe/src/domain/models"
	mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql"
	"gitee.com/captials-team/ubdframe/src/pkg/gin_http"
	v1log "gitee.com/captials-team/ubdframe/src/pkg/logs"
	"gitee.com/captials-team/ubdframe/src/pkg/passwd"
	"github.com/gin-gonic/gin"
)

type UserManageController struct {
	l              v1log.ILog
	conf           *configstc.UserAppConfig
	userModel      interfaces.ItfUser
	userThirdModel interfaces.ItfUserThird

	passwd.SaltMd5Password
	gin_http.ResponseController
	gin_http.OperateLogController
}

func NewUserManageController(l v1log.ILog, conf *configstc.UserAppConfig) *UserManageController {
	ctr := &UserManageController{
		l:               l,
		userModel:       mysqlDao.NewUserDao(conf.DBConfig),
		userThirdModel:  mysqlDao.NewUserThirdDao(conf.DBConfig),
		conf:            conf,
		SaltMd5Password: passwd.SaltMd5Password{Salt: conf.PasswordSalt},
	}

	return ctr
}

// SearchUser 用户列表 godoc
// @Summary      用户管理-列表
// @Description  用户列表展示和搜索
// @Tags         admin.user
// @Security     AdminKeyAuth
// @Produce      json
// @Param        param    body     reqdata.SearchUserParam  true  "搜索参数集"
// @success 0  {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.User}} "获取成功"
// @Router       /mag/user/search [post]
func (ctr *UserManageController) SearchUser(ctx *gin.Context) {
	var req reqdata.SearchUserParam
	ctx.ShouldBind(&req)

	params := &dto.SearchUserParams{
		Keywords: req.Keywords,
		Status:   req.Status,
	}

	list, pager, err := ctr.userModel.Search(params, &paginate.Pager{
		Page: req.Page,
		Size: req.Size,
	})
	if err != nil {
		ctr.l.Error("search err %s", err)
		ctr.Response(ctx, respdata.CError)
		return
	}

	ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{
		List:     list,
		Paginate: *pager,
	}))
}

// SaveUser  godoc
// @Summary      用户管理-保存
// @Description  创建或编辑用户
// @Tags         admin.user
// @Security     AdminKeyAuth
// @Produce      json
// @Param        param    body     reqdata.AddEditUserReq  true  "提交用户信息"
// @success 0  {object} respdata.ResponseData{data=respdata.DetailResp} "保存成功"
// @success 2  {object} respdata.ResponseData{} "系统繁忙"
// @success 4  {object} respdata.ResponseData{} "参数无效"
// @success 10  {object} respdata.ResponseData{} "未查询到"
// @Router       /mag/user/save [post]
func (ctr *UserManageController) SaveUser(ctx *gin.Context) {
	var req reqdata.AddEditUserReq

	ctx.ShouldBind(&req)

	if req.Id <= 0 {
		ctr.createUser(ctx, req)
	} else {
		ctr.updateUser(ctx, req)
	}
}

func (ctr *UserManageController) createUser(ctx *gin.Context, req reqdata.AddEditUserReq) {
	if req.Nickname == "" || req.Account == "" {
		ctr.Response(ctx, respdata.CParamsInvalid)
		return
	}

	salt := utils.RandLetterFigureCode(12)
	user := models.User{
		Account:  req.Account,
		Password: ctr.GenPassword(req.Password, salt),
		Nickname: req.Nickname,
		Phone:    req.Phone,
		Email:    req.Email,
		Status:   req.Status,
		Salt:     salt,
	}

	find, err := ctr.userModel.QueryByAccount(user.Account)
	if err != nil {
		ctr.l.Error("query err %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	if find != nil {
		ctr.Response(ctx, respdata.CError.MMsg("用户名已存在"))
		return
	}
	_, err = ctr.userModel.Add(&user)
	if err != nil {
		ctr.l.Error("add user err %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}

	ctr.CustomizeLog(ctx, "新增用户-"+user.Nickname)

	ctr.Response(ctx, respdata.CSuccess.MData(respdata.DetailResp{Id: user.Id}))
}

func (ctr *UserManageController) updateUser(ctx *gin.Context, req reqdata.AddEditUserReq) {
	if req.Nickname == "" || req.Account == "" {
		ctr.Response(ctx, respdata.CParamsInvalid)
		return
	}

	user := models.User{
		Account:  req.Account,
		Password: req.Password,
		Nickname: req.Nickname,
		Phone:    req.Phone,
		Email:    req.Email,
		Status:   req.Status,
	}

	find, err := ctr.userModel.Query(req.Id)
	if err != nil {
		ctr.l.Error("query err %s,uid=%d", err, req.Id)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	if find == nil {
		ctr.Response(ctx, respdata.CError.MMsg("用户不存在"))
		return
	}
	_, err = ctr.userModel.Update(req.Id, &user)
	if err != nil {
		ctr.l.Error("update err %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	if req.Password != "" {
		_, err = ctr.userModel.ResetPassword(req.Id, ctr.GenPassword(req.Password, find.Salt))
	}
	if err != nil {
		ctr.l.Error("update user err %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}

	ctr.CustomizeLog(ctx, "更新用户-"+user.Nickname)

	ctr.Response(ctx, respdata.CSuccess.MData(respdata.DetailResp{Id: user.Id}))
}

// QueryUser  godoc
// @Summary      用户管理-详情
// @Description  查询单个用户的详细信息
// @Tags         admin.user
// @Security     AdminKeyAuth
// @Produce      json
// @Param        param    body     reqdata.DetailReq  true  "查询指定id详情"
// @success 0  {object} respdata.ResponseData{data=respdata.QueryUserResp} "获取成功"
// @success 2  {object} respdata.ResponseData{} "系统繁忙"
// @success 4  {object} respdata.ResponseData{} "参数无效"
// @success 10  {object} respdata.ResponseData{} "未查询到"
// @Router       /mag/user/detail [post]
func (ctr *UserManageController) QueryUser(ctx *gin.Context) {
	var req reqdata.DetailReq

	ctx.ShouldBind(&req)
	if req.Id <= 0 {
		ctr.Response(ctx, respdata.CParamsInvalid)
		return
	}

	user, err := ctr.userModel.Query(req.Id)
	if err != nil {
		ctr.l.Error("query fail %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	if user == nil {
		ctr.Response(ctx, respdata.CNotFound)
		return
	}
	user.Password = ""

	thirds, _, err := ctr.userThirdModel.Search(&dto.SearchUserThirdParams{
		Uid: user.Id,
	}, &paginate.Pager{Size: 100})
	if err != nil {
		ctr.l.Error("get thirds fail %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}

	ctr.CustomizeLog(ctx, "查看用户-"+user.Nickname)

	resp := utils.CopyTo(user, new(respdata.QueryUserResp))
	resp.Thirds = utils.CopyMoreTo(thirds, []*respdata.UserThirdInfo{})

	ctr.Response(ctx, respdata.CSuccess.MData(resp))
}

// DisableUser godoc
// @Summary      用户管理-启用/禁用
// @Description  操作启用/禁用用户
// @Security     AdminKeyAuth
// @Tags         admin.user
// @Accept       json
// @Produce      json
// @Param        param    body     reqdata.SetStatusReq  true  "状态设置请求"
// @success 200  {object} respdata.ResponseData{} "设置成功"
// @Router       /mag/user/disable [post]
func (ctr *UserManageController) DisableUser(ctx *gin.Context) {
	var req reqdata.SetStatusReq

	ctx.ShouldBind(&req)

	if req.Status != consts.StatusEnable && req.Status != consts.StatusDisable {
		ctr.Response(ctx, respdata.CParamsInvalid)
		return
	}
	user, err := ctr.userModel.Query(req.Id)
	if err != nil {
		ctr.l.Error("query fail %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	if user == nil {
		ctr.Response(ctx, respdata.CNotFound)
		return
	}
	_, err = ctr.userModel.ResetStatus(req.Id, req.Status)
	if err != nil {
		ctr.l.Error("operate fail %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	if req.Status == consts.StatusEnable {
		ctr.CustomizeLog(ctx, "启用用户-"+user.Nickname)
	} else {
		ctr.CustomizeLog(ctx, "禁用用户-"+user.Nickname)
	}
	ctr.Response(ctx, respdata.CSuccess)
	return
}

// DeleteUser  godoc
// @Summary      用户管理-删除用户
// @Description  删除指定用户
// @Tags         admin.user
// @Security     AdminKeyAuth
// @Produce      json
// @Param        param    body     reqdata.DetailReq  true  "指定用户id"
// @success 0  {object} respdata.ResponseData{} "成功"
// @Router       /mag/user/delete [post]
func (ctr *UserManageController) DeleteUser(ctx *gin.Context) {
	var req reqdata.DetailReq
	ctx.ShouldBind(&req)
	if req.Id <= 0 {
		ctr.Response(ctx, respdata.CParamsInvalid)
		return
	}

	user, err := ctr.userModel.Query(req.Id)
	if err != nil {
		ctr.l.Error("query fail %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	if user == nil {
		ctr.Response(ctx, respdata.CNotFound)
		return
	}

	if _, err := ctr.userModel.Delete(user.Id); err != nil {
		ctr.l.Error("delete user fail %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}

	ctr.CustomizeLog(ctx, "删除用户-"+user.Nickname)

	ctr.Response(ctx, respdata.CSuccess)
}

// ResetUserPassword godoc
// @Summary      用户管理-重置密码
// @Description  密码重置
// @Security     AdminKeyAuth
// @Tags         admin.user
// @Accept       json
// @Produce      json
// @Param        param    body     reqdata.ResetUserPasswdReq  true  "重置密码请求"
// @success 200  {object} respdata.ResponseData{} "成功"
// @Router       /mag/user/reset_password [post]
func (ctr *UserManageController) ResetUserPassword(ctx *gin.Context) {
	var req reqdata.ResetUserPasswdReq
	ctx.ShouldBind(&req)

	if req.Password == "" {
		ctr.Response(ctx, respdata.CParamsInvalid)
		return
	}

	user, err := ctr.userModel.Query(req.Id)
	if err != nil {
		ctr.l.Error("query fail %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	if user == nil {
		ctr.Response(ctx, respdata.CNotFound)
		return
	}

	_, err = ctr.userModel.ResetPassword(req.Id, ctr.GenPassword(req.Password, user.Salt))
	if err != nil {
		ctr.l.Error("operate fail %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}
	ctr.CustomizeLog(ctx, "重置用户密码-"+user.Nickname)

	ctr.Response(ctx, respdata.CSuccess)
}
